using System;
using System.Collections;
using System.Text;
using AopAlliance.Intercept;
using Sedna.Core.Event.Parsers;
using log4net;

namespace Sedna.Core.Event
{
    public class BaseEventHandler: IEventHandler
    {
        private static ILog LOG = LogManager.GetLogger(typeof(BaseEventHandler));

        private IEventSourceParser eventSourceParser;
        private IEventGenerator eventGenerator;
        private IEventSender eventSender;
        private IList eventsToHandle;
        private IList eventFilters;

        public IEventSourceParser EventSourceParser
        {
            get { return eventSourceParser; }
            set { eventSourceParser = value; }
        }

        public IEventGenerator EventGenerator
        {
            get { return eventGenerator; }
            set { eventGenerator = value; }
        }

        public IEventSender EventSender
        {
            get { return eventSender; }
            set { eventSender = value; }
        }

        public IList EventsToHandle
        {
            get { return eventsToHandle; }
            set { eventsToHandle = value; }
        }

        public IList EventFilters
        {
            set { eventFilters = value; }
        }

        public bool CanHandle(string eventName)
        {
            return eventsToHandle.Contains(eventName);
        }

        public void Handle(EventfulAttribute eventfulAttribute, IMethodInvocation invocation, object invocationResult)
        {
            if (CanHandle(eventfulAttribute.Name))
            {
                Object eventSource = eventSourceParser.GetEventSource(invocation,
                                                                      eventfulAttribute,
                                                                      invocationResult);
                bool filterEvent = false;
                if (eventFilters != null)
                {
                    foreach (IEventFilter eventFilter in eventFilters)
                    {
                        if (eventFilter.Filter(eventfulAttribute.Name, eventSource))
                        {
                            filterEvent = true;
                            break;
                        }
                    }
                }
                
                if (!filterEvent)
                {
                    eventSender.Send(eventGenerator.GenerateEvent(eventfulAttribute.Name,
                                                                  eventSourceParser.GetEventSource(invocation,
                                                                                                   eventfulAttribute,
                                                                                                   invocationResult)));
                    #region Log Debug

                    if (LOG.IsDebugEnabled)
                    {
                        LOG.Debug(String.Format("Event: {0} has been sent by handler: {1}", eventfulAttribute.Name, GetType()));
                    }

                    #endregion
                }
            }
        }
    }
}
